/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.mycompany.chatapp.Databaseacces;

import java.io.IOException;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.xmldb.api.base.Collection;
import org.xmldb.api.base.XMLDBException;
import org.exist.xmldb.XQueryService;
import org.xmldb.api.base.ResourceIterator;
import org.xmldb.api.base.ResourceSet;
import org.xmldb.api.modules.XMLResource;
import org.xmldb.api.modules.XUpdateQueryService;



/**
 *
 * @author Grupo C
 */
public class ImpDBManager implements DBManager {

  
    private static ImpDBManager dbManagerInstance = null;
    private ImpXmlDbDataSource dataSource;
    private Properties queries= null;
    
    
    private ImpDBManager(){
        dataSource = ImpXmlDbDataSource.getinstanceDataSource();  
        //indicar fallo por no conexion
        try {
            queries=PropertyReader.readPropertyFile("consultas.properties");
        } catch (IOException ex) {
            Logger.getLogger(ImpDBManager.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
    
    
    public static synchronized ImpDBManager getInstanceManager(){
        
        
        if(dbManagerInstance==null)
        {
            dbManagerInstance=new ImpDBManager();
        }
        return dbManagerInstance;
        
    }
    
    public ImpDBActionResult execute(ImpDBAction aDBAction) {
        
         ImpDBActionResult result= new ImpDBActionResult();
        Object[] parameters= null;
        String query =null;
        Collection col= null;
         ResourceSet queryresult=null;
        boolean ok=true;
        List<Object> resultList=null;        
        String Type= ""; 
                 if (aDBAction.getActionId().matches("(?i)consulta.*")) Type = "search";
                 else if (aDBAction.getActionId().matches("(?i)insercion.*")) Type = "insert";
        
                 System.out.println("consulta: "+Type);
                 
                 
                 //Se conecta a la base de datos, mediante el xmldbdatamanager, y devuelve la coleccion
        try {          
            
              col= dataSource.getCollection();
        } catch (XMLDBException ex) {
            Logger.getLogger(ImpDBManager.class.getName()).log(Level.SEVERE, null, ex);
            ok=false;
            result.setResultWrong(ex,ex.getMessage());
            
        }
        
        
        
                
        //si es consulta
        
        if(Type.equals("search"))
        {
            try {
                //inicia el servicio de consulta
               XQueryService service =  (XQueryService) col.getService("XQueryService", "1.0");               
               
               //lee el dbaction y crea la query que el servicio necesita
                 query= getQueryMessage(aDBAction.getActionId(),aDBAction.getParameters());
                 

               //guarda el resultado de la query
                 queryresult = service.query(query);
            
                 //mapea la salida de la query a un objeto
                 
                 int typeOfObject=0;
                 if (aDBAction.getActionId().matches("(?i).*imagen.*")) typeOfObject=1;
                 else if (aDBAction.getActionId().matches("(?i).*autor.*")) typeOfObject=2;
                 
                 resultList=handleResult(queryresult,typeOfObject);
                 
            
            } catch (XMLDBException ex) {
                Logger.getLogger(ImpDBManager.class.getName()).log(Level.SEVERE, null, ex);
                //error de conexion
                ok=false;
                result.setResultWrong(ex,ex.getMessage());
            }
        
            
       if(ok){ result.setResultOk(resultList);}
        }
        
        //si es insercion
        else if( Type.equals("insert"))
        { if(aDBAction.getParameters().length>0){
             
            MessageFormat form = new MessageFormat(queries.getProperty(aDBAction.getActionId()));
            
            try {
                XUpdateQueryService service = (XUpdateQueryService) col.getService("XUpdateQueryService", "1.0");
                   
                String finalquery=form.format(aDBAction.getParameters());
                
                System.out.println("QUERYFINAL: "+finalquery);
                service.update(finalquery);
            
            
            } catch (XMLDBException ex) {
                 //error de conexion
                ok=false;
                result.setResultWrong(ex,ex.getMessage());
                Logger.getLogger(ImpDBManager.class.getName()).log(Level.SEVERE, null, ex);
            }
            
          
        }
        else{ ok=false; result.setResult("The query had no parameters");}
        
        }
         
            
        
        //retorna el dbresult
        
        
       
        return result;
    }
    
    
    
    //esta funcion devuelve la lista de propiedades que contiene las queries
    public Properties getProp()
    {
        
        return this.queries;
        
        
    }

    //este metodo coge las variables actionID y parameters del dbAction y devuelve un string que se puede
    //usar como query para el xQuery service

    private String getQueryMessage(String actionId, Object[] parameters) {
       String[] keywordsarray = (String[])parameters;
        String finalquery;
           
        if(parameters !=null){
               MessageFormat form = new MessageFormat(queries.getProperty(actionId));
        finalquery= form.format(keywordsarray);
           }
           else{
               
               finalquery=queries.getProperty(actionId);
           }
      

        
        return finalquery;
    }

    private List<Object> handleResult(ResourceSet queryresult,int type) throws XMLDBException {
       //parsea los resultados. por ahora solo saca una lista de fotos
        
        
        // Here we will store the Photo objects
	List<Object> result = new ArrayList();
        
        ResourceIterator i = queryresult.getIterator(); 
      
        while(i.hasMoreResources())
        {

	        XMLResource r = (XMLResource) i.nextResource();
          switch(type){
              case 1: Photo ph = new Photo();
                PhotoHandler handler = new PhotoHandler(ph);
                  r.getContentAsSAX(handler);
              result.add(ph);
                 break;
              case 2: User us = new User();
                  UserHandler handleru = new UserHandler(us);
                  r.getContentAsSAX(handleru);
                  result.add(us);
                  break;         
          
                    }          
           
        }

        return result;
  
    }
}
